﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CarbonExchange.Bll
{
    public class PledgeCategoryFactory : FactorySequenceBase<PledgeCategory>
    {
        protected override void MarkItemForDeletion(PledgeCategory item)
        {
            var tmp = item.Convert(DalContext);
            tmp.Deleted = true;
        }

        protected override void Validate(IQueryable<PledgeCategory> items, CarbonExchange.Bll.Exceptions.ValidationException exp)
        {
            items.Validate(exp, DalContext);
        }

        protected override void PopulateDataChanges(PledgeCategory item, object dataItem)
        {
            var tmp = dataItem as Dal.PledgeCategory;
            if (tmp != null)
            {
                item.Id = tmp.Id;
                item.CID = tmp.CID;
                item.SectionName = tmp.Section.Name;
            }
        }

        protected override object GetDataItemForUpdate(PledgeCategory item)
        {
            return item.Convert(DalContext);
        }

        internal class JoinHelper
        {
            internal Dal.PledgeCategory PledgeCategory { get; set; }
            internal string SectionName { get; set; }
        }

        private IQueryable<JoinHelper> GetSelection()
        {
            return DalContext.PledgeCategories.Where(x => !x.Deleted).OrderBy(x => x.Section.Sequence).ThenBy(x => x.Sequence).Select(x => new JoinHelper() { PledgeCategory = x, SectionName = x.Section.Name });
        }

        public IQueryable<PledgeCategory>  GetAllBySectionId(int sectionId)
        {
            return GetSelection().Where(x => x.PledgeCategory.SectionId == sectionId).Convert();
        }

        public IQueryable<PledgeCategory> GetAll(int sectionId)
        {
            return GetSelection().Convert();
        }

        public PledgeCategory GetById(int id)
        {
            return GetSelection().Where(x => x.PledgeCategory.Id == id).SingleOrDefault().Convert();
        }

        protected override void SetDalSequence(PledgeCategory item, int sequence)
        {
            var tmp = DalContext.PledgeCategories.Where(x => x.Id == item.Id && x.Sequence != sequence).SingleOrDefault();
            if (tmp != null)
            {
                tmp.Sequence = sequence;
            }
        }

        protected override void SetInitalSequence(IQueryable<PledgeCategory> items)
        {
            var tmpItems = items.Where(x => x.Id == 0).ToList();
            if (tmpItems.Count() > 1)
            {
                foreach (var item in tmpItems)
                {
                    item.Sequence = tmpItems.IndexOf(item);
                }
            }
        }
    }

    internal static class PledgeCategoryConverter
    {
        internal static PledgeCategory Convert(this CarbonExchange.Bll.PledgeCategoryFactory.JoinHelper source)
        {
            return ConvertItem(source);
        }

        internal static IQueryable<PledgeCategory> Convert(this IQueryable<CarbonExchange.Bll.PledgeCategoryFactory.JoinHelper> source)
        {
            return source.Select(x => ConvertItem(x));
        }

        private static PledgeCategory ConvertItem(CarbonExchange.Bll.PledgeCategoryFactory.JoinHelper item)
        {
            if (item != null)
            {
                return new PledgeCategory()
                {
                    Id = item.PledgeCategory.Id,
                    CID = item.PledgeCategory.CID,
                    Info = item.PledgeCategory.Info,
                    Name = item.PledgeCategory.Name,
                    SectionId = item.PledgeCategory.SectionId,
                    SectionName = item.SectionName,
                    Sequence = item.PledgeCategory.Sequence
                };
            }
            else
            {
                return null;
            }
        }

        internal static Dal.PledgeCategory Convert(this PledgeCategory source, Dal.Context context)
        {
            return ConvertItem(source, context);
        }

        internal static IQueryable<Dal.PledgeCategory> Convert(this IQueryable<PledgeCategory> source, Dal.Context context)
        {
            return source.Select(x => ConvertItem(x, context));
        }

        private static Dal.PledgeCategory ConvertItem(PledgeCategory item, Dal.Context context)
        {
            if (item != null)
            {
                Dal.PledgeCategory tmp = null;
                if (item.Id > 0)
                {
                    tmp = context.PledgeCategories.Where(x => x.Id == item.Id && !x.Deleted).Single();
                }
                else
                {
                    tmp = new CarbonExchange.Dal.PledgeCategory();
                    context.PledgeCategories.InsertOnSubmit(tmp);
                    int? tmpMax = context.PledgeCategories.Where(x => !x.Deleted && x.SectionId == item.SectionId).Select(x => (int?)x.Sequence).Max();
                    tmp.Sequence = tmp.Sequence + (tmpMax.HasValue ? tmpMax.Value + 1 : 0);
                }
                tmp.Info = item.Info;
                tmp.Name = item.Name;
                tmp.SectionId = item.SectionId;
                return tmp;
            }
            else
            {
                return null;
            }
        }

        internal static void Validate(this IQueryable<PledgeCategory> source, CarbonExchange.Bll.Exceptions.ValidationException e, Dal.Context context)
        {
            foreach (var item in source)
            {
                item.Validate(e, context);
            }
        }

        internal static void Validate(this PledgeCategory source, CarbonExchange.Bll.Exceptions.ValidationException e, Dal.Context context)
        {
        }
    }
}
